// src/modules/user/user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { UpdateProfileDto } from './dto/update-profile.dto';
import { ChangePasswordDto } from './dto/change-password.dto';
import { QueryUserDto } from './dto/query-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { User, UserStatus } from 'src/entities/user.entity';
import { BusinessException } from 'src/common/exceptions/business.exception';
import { ErrorCode } from 'src/common/constants/error-code.enum';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  // ==================== 个人资料管理 ====================

  /**
   * 创建用户（供认证模块使用）
   */
  async create(createUserDto: {
    username: string;
    email: string;
    password: string;
  }): Promise<User> {
    const user = this.userRepository.create({
      ...createUserDto,
      membershipLevel: 'free', // 默认免费用户
      status: 'active', // 默认正常状态
      role: 'user', // 默认普通用户角色
    });

    return await this.userRepository.save(user);
  }

  /**
   * 根据ID查找用户
   */
  async findById(id: string): Promise<User> {
    const user = await this.userRepository.findOne({
      where: { id },
    });

    if (!user) {
      throw new BusinessException(ErrorCode.USER_NOT_FOUND);
    }

    return user;
  }

  /**
   * 根据用户名查找用户
   */
  async findByUsername(username: string): Promise<User | null> {
    return this.userRepository.findOne({
      where: { username },
    });
  }

  /**
   * 根据邮箱查找用户
   */
  async findByEmail(email: string): Promise<User | null> {
    return this.userRepository.findOne({
      where: { email },
    });
  }

  /**
   * 根据邮箱或用户名查找用户
   * 注意：此方法会返回 password 字段，仅供认证使用
   */
  async findByIdentifier(identifier: string): Promise<User | null> {
    return this.userRepository.findOne({
      where: [{ email: identifier }, { username: identifier }],
      select: [
        'id',
        'username',
        'email',
        'password', // ✅ 显式包含 password 字段（用于登录验证）
        'status',
        'role',
        'membershipLevel',
        'membershipExpireAt',
        'createdAt',
      ],
    });
  }

  /**
   * 获取用户详情（不含密码）
   */
  async getProfile(userId: string) {
    const user = await this.findById(userId);

    return {
      id: user.id,
      username: user.username,
      email: user.email,
      nickname: user.nickname,
      avatar: user.avatar,
      phone: user.phone,
      bio: user.bio,
      status: user.status,
      role: user.role,
      membershipLevel: user.membershipLevel,
      membershipExpireAt: user.membershipExpireAt,
      createdAt: user.createdAt,
    };
  }

  /**
   * 更新个人资料
   */
  async updateProfile(userId: string, dto: UpdateProfileDto) {
    const user = await this.findById(userId);

    // 检查邮箱是否被占用
    if (dto.email && dto.email !== user.email) {
      const existingUser = await this.findByEmail(dto.email);
      if (existingUser) {
        throw new BusinessException(ErrorCode.EMAIL_ALREADY_EXISTS);
      }
    }

    // 更新用户信息
    Object.assign(user, dto);
    await this.userRepository.save(user);

    return this.getProfile(userId);
  }

  /**
   * 修改密码
   */
  async changePassword(userId: string, dto: ChangePasswordDto) {
    // 1. 检查新密码和确认密码是否一致
    if (dto.newPassword !== dto.confirmPassword) {
      throw new BusinessException(
        ErrorCode.BAD_REQUEST,
        '两次输入的密码不一致',
      );
    }

    // 2. 获取用户信息
    const user = await this.userRepository.findOne({
      where: { id: userId },
      select: ['id', 'password'], // 显式查询password字段
    });

    if (!user) {
      throw new BusinessException(ErrorCode.USER_NOT_FOUND);
    }

    // 3. 验证当前密码
    const isPasswordValid = await bcrypt.compare(
      dto.currentPassword,
      user.password,
    );

    if (!isPasswordValid) {
      throw new BusinessException(
        ErrorCode.INVALID_CREDENTIALS,
        '当前密码错误',
      );
    }

    // 4. 加密新密码
    const hashedPassword = await bcrypt.hash(dto.newPassword, 10);

    // 5. 更新密码
    await this.userRepository.update(userId, {
      password: hashedPassword,
    });

    return { message: '密码修改成功' };
  }

  /**
   * 上传头像
   */
  async updateAvatar(userId: string, avatarUrl: string) {
    await this.userRepository.update(userId, {
      avatar: avatarUrl,
    });

    return { avatarUrl };
  }

  // ==================== 用户管理（管理员） ====================

  /**
   * 获取用户列表（分页、搜索、筛选）
   */
  async getUserList(dto: QueryUserDto) {
    const { page = 1, limit = 10, keyword, status, roleId } = dto;

    const queryBuilder = this.userRepository
      .createQueryBuilder('user')
      .select([
        'user.id',
        'user.username',
        'user.email',
        'user.nickname',
        'user.avatar',
        'user.phone',
        'user.status',
        'user.role',
        'user.membershipLevel',
        'user.membershipExpireAt',
        'user.lastLoginAt',
        'user.createdAt',
      ]);

    // 关键词搜索
    if (keyword) {
      queryBuilder.andWhere(
        '(user.username LIKE :keyword OR user.email LIKE :keyword OR user.phone LIKE :keyword)',
        { keyword: `%${keyword}%` },
      );
    }

    // 状态筛选
    if (status) {
      queryBuilder.andWhere('user.status = :status', { status });
    }

    // 角色筛选
    if (roleId) {
      queryBuilder.andWhere('user.role = :role', { role: roleId });
    }

    // 分页
    const total = await queryBuilder.getCount();
    const users = await queryBuilder
      .skip((page - 1) * limit)
      .take(limit)
      .orderBy('user.createdAt', 'DESC')
      .getMany();

    return {
      data: users,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 获取用户详情（管理员）
   */
  async getUserDetail(userId: string) {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      select: {
        id: true,
        username: true,
        email: true,
        nickname: true,
        avatar: true,
        phone: true,
        bio: true,
        status: true,
        role: true,
        membershipLevel: true,
        membershipExpireAt: true,
        lastLoginAt: true,
        lastLoginIp: true,
        createdAt: true,
        updatedAt: true,
      },
    });

    if (!user) {
      throw new BusinessException(ErrorCode.USER_NOT_FOUND);
    }

    return user;
  }

  /**
   * 更新用户信息（管理员）
   */
  async updateUser(userId: string, dto: UpdateUserDto) {
    const user = await this.findById(userId);

    Object.assign(user, dto);
    await this.userRepository.save(user);

    return this.getUserDetail(userId);
  }

  /**
   * 封禁/解封用户
   */
  async toggleUserStatus(userId: string) {
    const user = await this.findById(userId);

    // 切换状态
    user.status =
      user.status === UserStatus.ACTIVE ? UserStatus.BANNED : UserStatus.ACTIVE;

    await this.userRepository.save(user);

    return {
      userId: user.id,
      status: user.status,
      message: user.status === UserStatus.BANNED ? '用户已封禁' : '用户已解封',
    };
  }

  /**
   * 删除用户（软删除）
   */
  async deleteUser(userId: string) {
    const user = await this.findById(userId);

    // 软删除
    await this.userRepository.softRemove(user);

    return { message: '用户已删除' };
  }

  // ==================== 统计分析 ====================

  /**
   * 获取用户统计
   */
  async getUserStats() {
    const total = await this.userRepository.count();
    const activeCount = await this.userRepository.count({
      where: { status: UserStatus.ACTIVE },
    });

    // 统计VIP和SVIP用户数
    const vipCount = await this.userRepository
      .createQueryBuilder('user')
      .where('user.membershipLevel IN (:...levels)', {
        levels: ['vip', 'svip'],
      })
      .getCount();

    const bannedCount = await this.userRepository.count({
      where: { status: UserStatus.BANNED },
    });

    // 最近7天新增用户
    const sevenDaysAgo = new Date();
    sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

    const recentCount = await this.userRepository
      .createQueryBuilder('user')
      .where('user.createdAt >= :date', { date: sevenDaysAgo })
      .getCount();

    return {
      total,
      activeCount,
      vipCount,
      bannedCount,
      recentCount,
    };
  }
}
